package com.ruoyi.business.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.business.domain.TRegisterInfo;
import com.ruoyi.business.domain.TRegisterLeave;
import com.ruoyi.business.domain.TRegisterNotice;
import com.ruoyi.business.domain.TRegisterSignSms;
import com.ruoyi.business.enums.*;
import com.ruoyi.business.payment.service.ITRegisterPaymentOrderService;
import com.ruoyi.business.payment.vo.TRegisterWillExpirationOrderVo;
import com.ruoyi.business.service.*;
import com.ruoyi.business.vo.TRegisterSignSendSmsVo;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Tellsea
 * @date 2024/2/2
 */
@Slf4j
@Component("registerTask")
@RequiredArgsConstructor
public class RegisterTask {

    private final ITRegisterInfoService registerInfoService;
    private final ITRegisterNoticeService registerNoticeService;
    private final ITRegisterLeaveService registerLeaveService;
    private final ITRegisterPaymentOrderService registerPaymentOrderService;
    private final ITRegisterSignSmsService tRegisterSignSmsService;

    private final SmsService smsService;

    @Value("${web.sign-url}")
    private String signUrl;

    public void updateStatus() {
//        updateNoticeStatus();
        updateCultureStatus();
        updateCurrentStatus();
    }

    public void updateNoticeStatus() {
        log.info("【更新通知状态 开始】");
        // 通知状态：待确认 => 延期未确认
        List<TRegisterInfo> registerInfoList = registerInfoService.list(Wrappers.<TRegisterInfo>lambdaQuery()
                .eq(TRegisterInfo::getNoticeStatus, NoticeStatusEnums.WAIT.getCode()));
        if (CollUtil.isNotEmpty(registerInfoList)) {
            List<Long> registerIdList = registerInfoList.stream().map(TRegisterInfo::getId).collect(Collectors.toList());
            List<TRegisterNotice> registerNoticeList = registerNoticeService.list(Wrappers.<TRegisterNotice>lambdaQuery()
                    .in(TRegisterNotice::getRegisterId, registerIdList)
                    .le(TRegisterNotice::getRegisterDate, DateUtil.format(DateUtil.date(), "yyyy/MM/dd")));
            if (CollUtil.isNotEmpty(registerNoticeList)) {
                List<Long> collect = registerNoticeList.stream().map(TRegisterNotice::getRegisterId).collect(Collectors.toList());
                registerInfoService.update(new TRegisterInfo().setNoticeStatus(NoticeStatusEnums.DELAYED.getCode()),
                        Wrappers.<TRegisterInfo>lambdaQuery()
                                .in(TRegisterInfo::getId, collect));
            }
        }
        log.info("【更新通知状态 结束】");
    }

    public void updateCultureStatus() {
        // 如果为报到状态为已报到、考核状态为未开始，且当前时间大于等于进修开始时间，则设置为进修中
        log.info("【更新考核状态 开始】");
        List<TRegisterInfo> registerInfoList = registerInfoService.list(Wrappers.<TRegisterInfo>lambdaQuery()
                .eq(TRegisterInfo::getSureStatus, SureStatusEnums.SUCCESS.getCode())
                .eq(TRegisterInfo::getCultureStatus, CultureStatusEnums.NO.getCode()));
        if (CollUtil.isNotEmpty(registerInfoList)) {
            List<Long> registerIdList = registerInfoList.stream().map(TRegisterInfo::getId).collect(Collectors.toList());
            List<TRegisterNotice> registerNoticeList = registerNoticeService.list(Wrappers.<TRegisterNotice>lambdaQuery()
                    .in(TRegisterNotice::getRegisterId, registerIdList)
                    // 开始时间 <= 当前时间 < 结束时间
                    .le(TRegisterNotice::getStartDate, DateUtil.format(DateUtil.date(), "yyyy/MM/dd"))
                    .gt(TRegisterNotice::getEndDate, DateUtil.format(DateUtil.date(), "yyyy/MM/dd")));
            if (CollUtil.isNotEmpty(registerNoticeList)) {
                List<Long> collect = registerNoticeList.stream().map(TRegisterNotice::getRegisterId).collect(Collectors.toList());
                registerInfoService.update(new TRegisterInfo().setCultureStatus(CultureStatusEnums.ING.getCode()),
                        Wrappers.<TRegisterInfo>lambdaQuery()
                                .in(TRegisterInfo::getId, collect));
            }
        }
        log.info("【更新考核状态 结束】");
    }

    public void updateCurrentStatus() {
        // 当前状态：在院、请假中、过期未销假
        log.info("【更新当前状态 开始】");
        // 当前在请假时间之间，改为请假中
        String currDate = DateUtil.format(DateUtil.date(), "yyyy/MM/dd");
        List<TRegisterLeave> registerLeaveList = registerLeaveService.list(Wrappers.<TRegisterLeave>lambdaQuery()
                .eq(TRegisterLeave::getEffectiveStatus, LeaveEffectiveStatusEnums.NORMAL.getCode())
                .lt(TRegisterLeave::getLeaveStartDate, currDate)
                .ge(TRegisterLeave::getLeaveEndDate, currDate)
                .or()
                .eq(TRegisterLeave::getLeaveStartDate, currDate)
                .eq(TRegisterLeave::getLeaveEndDate, currDate));
        if (CollUtil.isNotEmpty(registerLeaveList)) {
            List<Long> registerIdList = registerLeaveList.stream().map(TRegisterLeave::getRegisterId).distinct().collect(Collectors.toList());
            if (CollUtil.isNotEmpty(registerIdList)) {
                registerInfoService.update(new TRegisterInfo().setCurrentStatus(CurrentStatusEnums.WAIT.getCode()),
                        Wrappers.<TRegisterInfo>lambdaQuery()
                                .in(TRegisterInfo::getId, registerIdList));
            }
        }
        // 当前在请假时间之后，改为过期未销假
//        registerLeaveList = registerLeaveService.list(Wrappers.<TRegisterLeave>lambdaQuery()
//                .eq(TRegisterLeave::getEffectiveStatus, LeaveEffectiveStatusEnums.NORMAL.getCode())
//                .le(TRegisterLeave::getLeaveEndDate, currDate));
//        if (CollUtil.isNotEmpty(registerLeaveList)) {
//            List<Long> registerIdList = registerLeaveList.stream().map(TRegisterLeave::getRegisterId).distinct().collect(Collectors.toList());
//            if (CollUtil.isNotEmpty(registerIdList)) {
//                registerInfoService.update(new TRegisterInfo().setCurrentStatus(CurrentStatusEnums.SUCCESS.getCode()),
//                        Wrappers.<TRegisterInfo>lambdaQuery()
//                                .in(TRegisterInfo::getId, registerIdList));
//            }
//        }
        log.info("【更新当前状态 结束】");
    }

    public void updateCultureStatusForNoCulture(){
        log.info("【更新超时未结业变成已结业 开始】");
        registerInfoService.insertCultureStatusForNoCultureLog();
        registerInfoService.updateCultureStatusForNoCulture();
        log.info("【更新超时未结业变成已结业 结束】");
    }

    /**
     * 科主任签字短信提醒
     * @param noSignTimeOut 超时时间，单位小时.默认24小时
     * @param noSignTimes 发送短信倍数，默认10的倍数
     * @throws UnsupportedEncodingException
     */
    public void sendNoSignSmsToKSZ(Integer noSignTimeOut,Integer noSignTimes) throws UnsupportedEncodingException {
        if(noSignTimeOut==null){
            noSignTimeOut = 24;
        }
        if(noSignTimes==null){
            noSignTimeOut = 10;
        }
        log.info("【科主任签字短信提醒发送 开始，当前超时时间为：{}小时，累计超过倍数为：{}倍】",noSignTimeOut,noSignTimes);
        List<TRegisterSignSendSmsVo> noSendSmsSign = tRegisterSignSmsService.getNoSendSmsSign(noSignTimeOut,noSignTimes);
        if(noSendSmsSign!=null && !noSendSmsSign.isEmpty()){
            Map<String, List<TRegisterSignSendSmsVo>> groupResult = noSendSmsSign.stream().collect(Collectors.groupingBy(TRegisterSignSendSmsVo::getPhonenumber));
            for (Map.Entry<String, List<TRegisterSignSendSmsVo>> entry : groupResult.entrySet()) {
                Date nowDate = DateUtils.getNowDate();
                String phoneNumber = entry.getKey();
                List<TRegisterSignSendSmsVo> enList = entry.getValue();
                TRegisterSignSendSmsVo sendSmsVo = enList.get(0);
//                List<Long> registerIdList = new ArrayList<>();
                List<TRegisterSignSms> batchList = new ArrayList<>();
                for (TRegisterSignSendSmsVo smsVo : enList) {
//                    registerIdList.add(smsVo.getRegisterId());
                    TRegisterSignSms saveEntity = new TRegisterSignSms();
                    saveEntity.setRegisterId(smsVo.getRegisterId());
                    saveEntity.setRecvPhoneNumber(phoneNumber);
                    saveEntity.setSendTime(nowDate);
                    saveEntity.setRecvUserId(sendSmsVo.getManageUserId());
                    batchList.add(saveEntity);
                }
                String urlParams="type=sign&userId="+sendSmsVo.getManageUserId()+"&userName="+sendSmsVo.getUserName();
                String url=signUrl+"?"+ URLEncoder.encode(urlParams, "UTF-8");
                String msg = sendSmsVo.getNickName()+"老师，您好：根据行风办规定，您需要为"+sendSmsVo.getRegisterDeptName()+"的进修学员批量签署行风自律承诺书，请点击链接后签字。"+url;
                // 发短信
                smsService.sendMessage(phoneNumber,msg);
                tRegisterSignSmsService.saveBatch(batchList);
            }

        }
        log.info("【科主任签字短信提醒发送 结束】");
    }

    /**
     * 关闭逾期未支付订单
     * @throws Exception e
     */
    public void timeOutClosePayOrder() throws Exception {
        registerPaymentOrderService.queryForTimeOutOrder();
    }

    /**
     * 支付快过期订单
     * @throws Exception e
     */
    public void willPayExpiration() throws Exception {
        List<TRegisterWillExpirationOrderVo> orderVos = registerPaymentOrderService.queryWillExpirationOrder();
        for (TRegisterWillExpirationOrderVo orderVo : orderVos) {
            Date expirationTime = orderVo.getExpirationTime();
            String yearStr = DateUtil.format(expirationTime, "YYYY");
            String dateStr = DateUtil.format(expirationTime, "MM月dd日");
            String msg = "您在华山医院的进修申请（"+orderVo.getRegisterDeptName()+" " +
                    "科 "+orderVo.getRegisterYear()+"年+"+orderVo.getBatchName()+" 批次），" +
                    "其进修费即将在"+yearStr+"的"+dateStr+"到期无法支付，届时将转为逾期状态。请使用电脑登录进修系统，进入 个人中心 后点击 我的进修 完成支付。";
            customSendMessage(orderVo.getPhoneNumber(), msg);
        }
    }

    /**
     * 自定义短信发送
     * @param phoneNumber 手机号
     * @param msg 短信
     */
    public void customSendMessage(String phoneNumber,String msg) {
        if(StringUtils.isEmpty(phoneNumber) || StringUtils.isEmpty(msg)){
            log.error("发送短信的手机号和消息不能为空");
            return;
        }
        smsService.sendMessage(phoneNumber, msg);
    }

}
